///********************************************************************
///* Copyright © 2012 fishr (fishr.flash@gmail.com)  
///********************************************************************


package su.fishr.social_network.OK.uploadV2 
{
	
	import api.com.adobe.images.PNGEncoder;
	import api.com.adobe.json.JSON;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.utils.ByteArray;
	import su.fishr.social_network.OK.uploadV2.requests.*;
	import su.fishr.utils.Dumper;
	
	
	/**
	 *   Основной класс загрузчика фотографии (изображения)
	 * в альбом пользователя через 
	 * <a href="http://dev.odnoklassniki.ru/wiki/display/ok/REST+API+-+photo+upload+V2"> API 2.0 Odnoklassniki</a>.
	 * <p>
	 * 
	 * <b>Примечание.</b> Для работы плагина ( вычисления хеш-подписи, кодирования изображения,
	 * json-декодирования) необходимы дополнительные
	 * классы, которые есть в составе 
	 * <a href="http://dev.odnoklassniki.ru/wiki/download/attachments/1343532/odkl_as3_sdk.zip">SDK API Odnoklassniki</a>,
	 * в пакете <code>api.com.adobe</code>.
	 * Необходимо подключить SDK к проекту.
	 * </p>
	 * 
	 * 	@example	<i>Пример использования:</i>
	 * <listing version="3.0">
		package 
		{
			import flash.display.Bitmap;
			import flash.display.BitmapData;
			import flash.display.Sprite;
			import flash.display.StageAlign;
			import flash.display.StageScaleMode;
			import flash.events.Event;
			import su.fishr.social_network.OK.uploadV2.DataPhoto;
			import su.fishr.social_network.OK.uploadV2.UploaderPhotoV2;
			
			
			public class Main extends Sprite 
			{
				/// гл. класс приложения
				public function Main():void 
				{
					if (stage) init();
					else addEventListener(Event.ADDED_TO_STAGE, init);
				}
				
				///инициализация
				private function init(e:Event = null):void 
				{
					removeEventListener(Event.ADDED_TO_STAGE, init);
					// entry point
					
					this.stage.scaleMode = StageScaleMode.NO_SCALE;
					this.stage.align = StageAlign.LEFT;
					
					/// в качестве примера отрисовываем сцену в массив BitmapData
					const bData:BitmapData = new BitmapData( this.stage.stageWidth, this.stage.stageHeight, false );
					bData.draw( this );
					
					/// создаем объект Bitmap
					const bt:Bitmap = new Bitmap( bData );
					
					/// создаем структурированный объект dataPhoto
					const dataPhoto:DataPhoto = new DataPhoto( callBack, bt, "this is me", "myPhoto" );
					
					/// начинаем загрузку фотографии (изображения)
					new UploaderPhotoV2( dataPhoto, this.loaderInfo.parameters );
				}
				
				/// сюда будет возвращен результат загрузки
				private function callBack( result:String ):void
				{
					switch ( result ) 
					{
						case UploaderPhotoV2.ANOTHER_ERROR :
							trace( "what the error ( " );
							/// some action
						break; 
						
						case UploaderPhotoV2.NO_BODY_PHOTO:
							trace( "no photo (" );
							/// another action
						break;
						
						case UploaderPhotoV2.NO_ACCESS_PHOTOALBUM:
							trace( "Please give access to the album!" );
						break;

						default:
							trace( "Congratulations! Your photo added in album!");
							

					}
				}
				
			}
			
		}
	 * </listing>
	 * 
	 * 
	 * @playerversion          Flash 10
	 * @langversion            3.0
	 * @author                 fishr
	 * @created                12.05.2012 1:45
	 * @since                  12.05.2012 1:45
	 */
	public  class UploaderPhotoV2
	{
	
	/**-------------------------------------------------------------------------------
	* 
	*	   						V A R I A B L E ' S 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		/**
		 * Значение сообщается в аргументах функции обратного вызова
		 * в случае если данные об изображении не обнаружены в полученом
		 * объекте DataPhoto.
		 * 
		 * @see DataPhoto
		 */
		static public const NO_BODY_PHOTO:String = "noBodyPhoto";
		/**
		 * Значение сообщается в аргументах функции обратного вызова
		 * в случае если пользователь не разрешил доступ к своему фотоальбому
		 */
		static public const NO_ACCESS_PHOTOALBUM:String = "noAccessPhotoalbum";
		/**
		 * "Другая ошибка", передается в функцию обратного вызова (callback) в любых случаях
		 * когда возникшая ошибка не связана с отсутствием данных изображения или недоступности
		 * пользовательского альбома.
		 */
		static public const ANOTHER_ERROR:String = "anotherError";
		
		static private const AUTHOR:String = "fishr (fishr.flash@gmail.com)";
		
		private var _callback:Function;
		private var _photo:ByteArray;
		private var _parameters:Object;
		private var _jsonResp:Object;
		private var _commentPhoto:String;
		private var _photoName:String;
		
	//}
	
	/**-------------------------------------------------------------------------------
	* 
	*								P U B L I C 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		/**
		 * 
		 *  Создает экземпляр плагина загрузчика фотографий. Который, используя
		 * полученные в аргументах вызова данные, сразу начинает взаимодействие
		 * с <a href="http://dev.odnoklassniki.ru/wiki/display/ok/REST+API+-+photo+upload+V2"> API 2.0 Odnoklassniki</a> и загрузку (upload) фотографии (изображения)
		 * в фотографии пользователя.
		 * 
		 * @param	data специальный объект данных ( <a href="DataPhoto.html"><code>DataPhoto</code></a> ) 
		 * 				 содержащий структурированную информацию касающуюся 
		 * 				 загружаемого изображения.
		 * @param	parameters объект данных <code>FlashVars</code>. 
		 *                 Содержит все необходимые данные для 
		 *                 запросов к <a href="http://dev.odnoklassniki.ru/wiki/display/ok/REST+API+-+photo+upload+V2"> API V2.0 Odnoklassniki</a>. Обычно это объект
		 * 				   возвращаемый loaderInfo#parameters главного класса приложения. 
		 * 				   Например : <code>Main.loaderInfo.parameters</code>.
		 * 
		 * @see DataPhoto
		 * @see http://help.adobe.com/ru_RU/FlashPlatform/reference/actionscript/3/flash/display/LoaderInfo.html#parameters flash.display.LoaderInfo#parameters
		 */
		public function UploaderPhotoV2( data:DataPhoto, parameters:Object)
		{
			super();
			
			init( data, parameters );
		}
		
		//comment line
	//}
	
	/**-------------------------------------------------------------------------------
	* 
	*								P R I V A T E 	
	* 
	* --------------------------------------------------------------------------------
	*/	
	//{
		private function init( data:DataPhoto, parameters:Object):void 
		{
			_callback = data.callback;
			
			if ( !( _callback ) ) 
			{
				throw new Error( "Error: Should be a callback function" );
				return;
			}
			if ( data.photoValue is Bitmap && data.photoValue.bitmapData ) _photo = PNGEncoder.encode( data.photoValue.bitmapData);
			else if ( data.photoValue is BitmapData ) _photo = PNGEncoder.encode( data.photoValue as BitmapData );
			else if ( data.photoValue is ByteArray ) _photo = data.photoValue as ByteArray;
			
			_commentPhoto = data.comment;
			_photoName = data.photoName;
			
			if ( !_photo )
			{
				_callback( UploaderPhotoV2.ANOTHER_ERROR );
				throw new Error( UploaderPhotoV2.NO_BODY_PHOTO );
				return;
			}
			
			/*
			Состав флешварсов полученных при загрузке флеш приолжения
			на страницу Одноклассников.
			
			[009] > 	application_key:(str,17) XXXXX
			[010] > 	auth_sig:(str,32) XXXXXXXXXXXXXXXXXXXXXXX
			[011] > 	session_key:(str,59) XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
			[012] > 	web_server:(str,20) www.odnoklassniki.ru
			[013] > 	logged_user_id:(str,12) XXXXXXXXXXX
			[014] > 	authorized:(str,1) 1
			[015] > 	api_server:(str,28) http://api.odnoklassniki.ru/
			[016] > 	sig:(str,32) b50da1f8cd6c5f22635442c5c21ad6d0
			[017] > 	first_start:(str,1) 0
			[018] > 	session_secret_key:(str,32) 142e610b891d8c5631d6a46dd9240e15
			[019] > 	apiconnection:(str,22) 89958656_1338329792322
			[020] > 	clientLog:(str,1) 0*/
			
			
			
			
			_parameters = parameters;
			
			/**
			 * Выполнение первого запроса. В документации именуется как "photosV2.getUploadUrl"
			 */
			try
			{
				new GetUploaderURL( resultGetUpload, errorHandler, parameters );
			}
			catch ( err:Error )
			{
				errorHandler( err );
			}
				
		}
		

		/**
		 *  Обрабатывает ответ первого запроса
		 * выполняет непосредственную загрузку фото
		 * на image-server системы Odnoklassniki
		 * @param	data - ответ сервера в формате json на запрос photosV2.getUploadUrl
		 */
		private function resultGetUpload( data:Object ):void
		{
			/*
			 * Ожидаемый ответ
			 
				{"photo_ids":
					["XiKOrqwTEGy0olwUdG0q4HL5xIwo/4KassmkB7J7rG0hQ7WdEknvzg=="],
				"upload_url":
					"http://up.odnoklassniki.ru/uploadImage?apiToken=G24hc3r7QpC0eZt4cR%2BBkNsLRua2rpPLdupqLJilBXeIavUofxgRaabWD%2FDNqAz3zY8EorBoQBrcXePz3Mf%2B6g%3D%3D&photoIds=tJ0mUPMtfnLvOb26mO5BtGS8rm4ZjJVLzaWSNCmvLcKc82MqAsw7lg%3D%3D",
					"expires":"2012.05.31 01:39"}
				
			*/
			if ( errorHandler( data ) ) return;	
			
			_jsonResp = JSON.decode( String( data ) );
			
			/**
			 *  Второй запрос. В документации "photo upload via HTTP POST".
			 */
			new UploadPhoto( resultUpload, errorHandler,  _jsonResp.upload_url, _photo, _photoName );
			
		}
		
		/**
		 * Обрабатывает результат непосредственной загрузки 
		 * бинарного массива изображения. Ответ приходит в формате
		 * json.
		 * @param	data
		 */
		private function resultUpload( data:String ):void
		{
			/*
			 * Примерный ответ:
			 * 
				{"photos":
					{"XiKOrqwTEGy0olwUdG0q4HL5xIwo/4KassmkB7J7rG0hQ7WdEknvzg==":
					{"token":"4VG5RbWS/IAlVAV1FIL0nFE36mBhEioqvD97dxI1T8Gx52uok1Uuq59nlhGov6aSOjXKRqacoEtHsGQU8stlxQ\u003d\u003d"}
					}
				}
			*/

			const respond:Object = JSON.decode( data );
			
			if ( respond.error_code )
			{
				errorHandler( data );
				return;
			}
			
			new CommitPhoto( _callback, errorHandler, _parameters, {photo_id: _jsonResp.photo_ids[0], token: respond.photos[  _jsonResp.photo_ids[0] ]["token"], comment:_commentPhoto  }  );
		}
		
		/**
		 *  Обрабатывает ошибки процесса загрузки
		 * изображения.
		 * 
		 * @param	dataError
		 * @return
		 */
		private function errorHandler( dataError:Object ):Boolean
		{
			const resp:String = dataError as String;
			if ( resp.indexOf( "must grant an access" ) !== -1)
			{
				_callback( UploaderPhotoV2.NO_ACCESS_PHOTOALBUM );
				_callback = null;
				
				return true;
			}
			else if ( resp.indexOf( "error" ) !== -1 )
			{
				_callback( UploaderPhotoV2.ANOTHER_ERROR );
				_callback = null;
			}
			
			return false;
		}
		
	//}
		
		
	}

}